~~~c++
#include <iostream>
#include <string>
#include <sys/epoll.h>
#include <unistd.h>
#include <netinet/in.h>
#include <map>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <cstring>
using namespace std;

// 最大客户端连接数
const int MAX_CONM = 1024;

// 保存客户端的信息
struct Client
{
    int sockfd;  // 客户端套接字
    string name; // 客户端名称
};

int main()
{

    // 这里是创建服务端监听的socket：相当于电话
    int listensock = socket(AF_INET, SOCK_STREAM, 0);
    if (listensock < 0)
    {
        perror("创建监听socket失败");
        return -1;
    }

    // 设置SO_REUSEPORT选项（如果操作系统支持）,允许多个套接字绑定到同一个端口上
    int opt = 1;
#ifdef SO_REUSEPORT
    if (setsockopt(listensock, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)) < 0)
    {
        perror("setsockopt(SO_REUSEPORT) failed");
        close(listensock);
        exit(EXIT_FAILURE);
    }
#endif

    // 绑定本地的ip和端口：给电话插上电话卡
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;                          // 输入协议
    addr.sin_addr.s_addr = inet_addr("192.168.92.128"); // 让本机的ip都绑定socket;
    addr.sin_port = htons(5005);                        // 绑定5005这个端口
    int rec = bind(listensock, (struct sockaddr *)&addr, sizeof(addr));
    if (rec < 0)
    {
        perror("绑定失败");
        return -1;
    }

    // 监听客户端是否有事件:比如客户端连接上来或客户端发送消息;
    int ret = listen(listensock, MAX_CONM);
    if (ret < 0)
    {
        perror("调用监听函数失败");
        return -1;
    }

    // 创建epoll实例
    int epld = epoll_create(1);
    if (epld < 0)
    {
        perror("创建epoll实例失败");
        return -1;
    }

    // 将监听socket放入epoll实例中,
    struct epoll_event ev;
    ev.events = EPOLLIN;
    ev.data.fd = listensock;
    int res = epoll_ctl(epld, EPOLL_CTL_ADD, listensock, &ev);
    if (res < 0)
    {
        perror("添加socket进入epoll实例失败");
        return -1;
    }

    // 保存客户的信息，创建一个map对象
    map<int, Client> clients;
    printf("等待客户端连接!!!\n");

    // 进行监听循环
    while (true)
    {
        struct epoll_event evs[MAX_CONM]; // 用来存储发生事件的socket的信息

        int n = epoll_wait(epld, evs, MAX_CONM, -1); //-1表示无限等待，返回的n表示有多少个socket发生事件
        if (n < 0)
        {
            perror("epoll_wait调用失败");
            return -1;
        }

        for (int i = 0; i < n; i++)
        {
            int fd = evs[i].data.fd;
            if (fd == listensock) // 如果fd是监听socket有事件
            {
                struct sockaddr_in client_addr;
                socklen_t client_addr_len = sizeof(client_addr);
                // 从监听套接字队列中提取第一个连接请求，并返回一个新的套接字描述符
                int clientsock = accept(listensock, (struct sockaddr *)&client_addr, &client_addr_len);
                if (clientsock < 0)
                {
                    printf("%d\n", clientsock);
                    perror("accept函数调用失败");
                    continue;
                }
                printf("套接字为:%d ip为%s的客户端连接成功。。。。。。。。\n", clientsock, inet_ntoa(client_addr.sin_addr));
                // 则将客户端的socket加入epoll实例
                struct epoll_event ev_client;
                ev_client.events = EPOLLIN;
                ev_client.data.fd = clientsock;
                int rea = epoll_ctl(epld, EPOLL_CTL_ADD, clientsock, &ev_client);
                if (res < 0)
                {
                    printf("%d\n", clientsock);
                    perror("添加clientsock进入epoll实例失败");
                    continue;
                }

                // 将客户端信息保存
                Client client;
                client.sockfd = clientsock;
                client.name = "";
                clients[clientsock] = client;
            }
            else // 如果发生事件的是客户端
            {
                char buffer[1024];                 // 定义一个字符数组，用来存储从客户端接受到的信息
                memset(buffer, 0, sizeof(buffer)); // 清空接收缓冲区
                int n = recv(fd, buffer, 1023, 0);
                if (n < 0)
                {
                    perror("recv函数调用失败");
                    break;
                }
                else if (n == 0)
                {
                    printf("客户端断开连接!!!");
                    close(fd);
                    epoll_ctl(epld, EPOLL_CTL_DEL, fd, 0);
                    clients.erase(fd);
                }
                else
                {
                    std::string buffers(buffer, n); // 直接使用构造函数处理接收到的数据
                    if (clients[fd].name == "")
                    {
                        clients[fd].name = buffers;
                    }
                    else
                    {
                        std::string name = clients[fd].name;
                        // 将消息发送给其他客户端
                        for (auto &ii : clients)
                        {
                            if (ii.first != fd)
                            {
                                std::string message = "[" + name + "]: " + buffers;
                                send(ii.first, message.c_str(), message.size(), 0);
                            }
                        }
                    }
                }
            }
        }
    }
    close(epld);       // 关闭epoll实例
    close(listensock); // 关闭监听的socket
    return 0;
}

~~~

